package com.authine.cloudpivot.ext.controller;


import com.authine.cloudpivot.engine.api.model.bizmodel.BizPropertyModel;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizCommentModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkItemModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkflowInstanceModel;
import com.authine.cloudpivot.engine.api.model.workflow.WorkflowTokenModel;
import com.authine.cloudpivot.engine.enums.status.WorkItemStatus;
import com.authine.cloudpivot.engine.enums.type.ActionType;
import com.authine.cloudpivot.engine.enums.type.FormActionType;
import com.authine.cloudpivot.engine.workflow.model.activity.Activity;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.api.controller.runtime.WorkflowInstenceRuntimeController;
import com.authine.cloudpivot.web.api.helper.WorkflowInstanceHelper;
import com.authine.cloudpivot.web.api.helper.WorkflowInstanceOptions;
import com.authine.cloudpivot.web.api.util.DateUtils;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import com.authine.cloudpivot.web.api.view.runtime.ApprovalVO;
import com.authine.cloudpivot.web.api.view.runtime.WorkItemApprovalVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/public/approval")
@Slf4j
public class FZVApprovalsController extends WorkflowInstenceRuntimeController {


    @GetMapping("/logs")
    public List<ApprovalModel> getApprovals(@RequestParam(required = true, name = "workflowInstanceId") String workflowInstanceId){

        List<ApprovalModel> result = new ArrayList<>();
        List<WorkItemApprovalVO> workItemApprovalVOS = handleWorkItemApprovalsExt(workflowInstanceId);

        if (CollectionUtils.isNotEmpty(workItemApprovalVOS)){
            for (WorkItemApprovalVO approvalVO : workItemApprovalVOS){
                List<ApprovalVO> nodes = approvalVO.getNodes();
                if (CollectionUtils.isNotEmpty(nodes)){
                    for (ApprovalVO node : nodes){
                        ApprovalModel model = new ApprovalModel();
                        model.setActivityName(approvalVO.getActivityName());
                        model.setActivityResult(approvalVO.getActivityStatus().getName());
                        model.setApprovalTime(node.getApprovalTime());
                        if (node.getApprovaler() != null){
                            model.setApprovaName(node.getApprovaler().getName());
                        }
                        if (node.getBizComment() != null){
                            model.setContent(node.getBizComment().getContent());
                        }
                        model.setDeptName(node.getDept());
                        result.add(model);
                    }
                }

            }
        }
        return result;
    }

    protected List<WorkItemApprovalVO> handleWorkItemApprovalsExt(String workflowInstanceId) {
        String userId = getUserId();
        List<WorkItemApprovalVO> workItemApprovals = Lists.newArrayList();
        WorkflowInstanceOptions workflowInstanceOptions = WorkflowInstanceOptions.builder()
                .setWorkflowInstanceId(workflowInstanceId)
                .setQueryCirculate(false)
                .setDubboConfigService(getDubboConfigService())
                .build();

        List<WorkItemModel> workItems = workflowInstanceOptions.getWorkItems();
        List<WorkItemModel> workItemsFinished = workflowInstanceOptions.getWorkItemsFinished();
        List<WorkflowTokenModel> workflowTokenModels = workflowInstanceOptions.getWorkflowTokens();
        List<BizCommentModel> bizComments = workflowInstanceOptions
                .filterBizCommentModelNotEquals(ActionType.CIRCULATE);
        bizComments = bizComments.stream().filter(t -> {
            return t.getResult() != FormActionType.TS;
        }).collect(Collectors.toList());
        List<WorkflowInstanceModel> subInstances = workflowInstanceOptions.getSubInstances();

        List<WorkItemModel> workItemModelList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(workItems)) {
            workItemModelList.addAll(workItems);
        }

        if (CollectionUtils.isNotEmpty(workItemsFinished)) {
            workItemModelList.addAll(workItemsFinished);
        }

        WorkflowInstanceHelper workflowInstanceHelper = new WorkflowInstanceHelper(this.getWorkflowInstanceFacade(),
                this.getAppManagementFacade(), this.getBizObjectFacade(), this.getOrganizationFacade());
        Map<String, UserModel> workItemsAllParticipants = workflowInstanceHelper.getParticipantMap(workItemModelList);// 待办用户+已办用户
//		Map<String, UserModel> workItemsParticipants = workflowInstanceHelper.filterParticipantUser(workItems,
//				workItemsAllParticipants);// 待办用户
        Map<String, List<String>> departs = workflowInstanceHelper.disposeDeparts(bizComments, workItemsAllParticipants,
                workflowInstanceOptions.getInstance());

        // 给缺少tokenid的审批意见补全tokenid
        workflowInstanceHelper.bizCommentCompletion(bizComments, workflowTokenModels);
        Map<Integer, List<BizCommentModel>> comments = bizComments.stream()
                .collect(Collectors.groupingBy(BizCommentModel::getTokenId));
        List<BizPropertyModel> properties = null;
        if (comments != null && comments.size() > 0) {
            properties = getAppManagementFacade().getBizSchemaBySchemaCode(workflowInstanceOptions.getTemplate().getSchemaCode(), true).getProperties();
        }
        // 获取最大token值
        int maxToken = Collections
                .max(workflowTokenModels.stream().map(WorkflowTokenModel::getTokenId).collect(Collectors.toList()));
        WorkItemApprovalVO workItemApproval;

        for (int i = 0; i <= maxToken; i++) {
            // 处理子节点信息
            int finalI = i;
            WorkflowTokenModel workflowTokenModel = workflowTokenModels.stream().filter(t -> t.getTokenId() == finalI)
                    .findAny().orElse(null);
            Activity activity = workflowInstanceOptions.getActivity(workflowTokenModel.getActivityCode());
            boolean isStart = workflowInstanceOptions.isStartActivity(activity);
            log.debug("activity code = {}", activity == null ? StringUtils.EMPTY : activity.getActivityCode());

            List<BizCommentModel> commentTemplate = comments.get(finalI);

            if (CollectionUtils.isNotEmpty(commentTemplate)) {
              //  (    Boolean isStart, List<CirculateItemModel> circulateItemModel, Map<String, UserModel> circulateAllParticipants, Map<String, List<String>> circulateDeparts)
                workItemApproval = workflowInstanceHelper.handleApprovalWithComment(commentTemplate, activity,
                        workItemsAllParticipants, departs, workItemModelList, properties, workItems, workItemsFinished,
                        workflowTokenModel, isStart,null,null,null);
            } else {
                workItemApproval = workflowInstanceHelper.handleApprovalWithActivity(workflowTokenModel, activity,
                        subInstances, workItemsAllParticipants, departs, workItemModelList, isStart,null,null,null);
            }

            if (workItemApproval != null) {
                workItemApproval.setTokenId(workflowTokenModel.getTokenId());
                workItemApprovals.add(workItemApproval);

                if (workItemApproval.getNodes() != null) {
                    workItemApproval.getNodes().stream().forEach(approvalVO -> {
                        //当前用户查看自己的审批日志，把未启动状态改为进行中状态
                        if (approvalVO != null && approvalVO.getApprovaler() != null && userId != null
                                && userId.equals(approvalVO.getApprovaler().getId())
                                && approvalVO.getWorkItemStatus() == WorkItemStatus.NOTSTARTED) {
                            approvalVO.setWorkItemStatus(WorkItemStatus.INPROGRESS);
                        }
                    });
                }
            }
        }
        return workItemApprovals;
    }

    /**
     * 保存流程表单日志
     */
    @PostMapping("saveApprovalLog")
    public void saveApprovalLog(@RequestParam String approColoumn, @RequestParam String instanceId){

        WorkflowInstanceModel workflowInstance = getWorkflowInstanceFacade().getWorkflowInstance(instanceId);
        String bizObjectId = workflowInstance.getBizObjectId();
        String schemaCode = workflowInstance.getSchemaCode();
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(schemaCode, bizObjectId);

        List<ApprovalModel> approvals = getApprovals(instanceId);
        List<HashMap> approvalList = new ArrayList<>(approvals.size());
        if (CollectionUtils.isNotEmpty(approvals)){
            for (ApprovalModel model : approvals){
                HashMap map = new HashMap();
                map.put("parentId",bizObjectId);
                map.put("activityName", model.getActivityName());
                map.put("activityResult", model.getActivityResult());
                map.put("approvalTime", DateUtils.getDate(model.getApprovalTime(),"yyyy-MM-dd HH:mm:ss"));
                map.put("approvaName", model.getApprovaName());
                map.put("content", model.getContent());
                map.put("deptName", model.getDeptName());
                approvalList.add(map);
            }
            bizObject.getData().put(approColoumn,approvalList);
        }


        String object = getBizObjectFacade().saveBizObject(bizObject.getOwner().getId(), bizObject, false);
    }


    @GetMapping("/addPrintCount")
    public void addPrintCount(String objectId, String schemaCode, String printColumn){
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(schemaCode, objectId);
        Object count = bizObject.getData().get(printColumn);
        if (count == null){
            bizObject.getData().put(printColumn,1);
        } else {
            BigDecimal bigDecimal = (BigDecimal)count;
            bizObject.getData().put(printColumn,bigDecimal.add(new BigDecimal(1)));
        }

        getBizObjectFacade().saveBizObject(bizObject.getOwner().getId(), bizObject, false);
    }
}
